/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {
    AliasType,
    ArkAliasTypeDefineStmt,
    ArkArrayRef,
    ArkAssignStmt,
    ArkField,
    ArkFile,
    ArkInstanceFieldRef,
    ArkInvokeStmt,
    ArkMethod,
    ArkNewArrayExpr,
    ArkParameterRef,
    ArkReturnStmt,
    ArkReturnVoidStmt,
    ArrayType,
    ClassType,
    FunctionType,
    LiteralType,
    Local,
    Stmt,
    StringType,
    TupleType,
    UnclearReferenceType,
    UnionType,
    UnknownType,
} from 'arkanalyzer/lib';
import { Rule } from "../../model/Rule";

import { ArkClass, ClassCategory } from "arkanalyzer/lib/core/model/ArkClass";
import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger';
import {BaseChecker, BaseMetaData } from '../BaseChecker';
import { Defects, IssueReport } from "../../model/Defects";
import {
    ClassMatcher,
    FieldMatcher,
    FileMatcher,
    MatcherCallback,
    MatcherTypes,
    MethodMatcher,
} from "../../matcher/Matchers";
import { FieldCategory } from 'arkanalyzer/lib/core/model/ArkField';
import { NumberConstant, StringConstant, UndefinedConstant } from 'arkanalyzer/lib/core/base/Constant';
import { RuleListUtil } from '../../utils/common/DefectsList';

const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'NoTypeAlias');
type NoTypeAliasOptions = [
    {
        allowAliases?: string,
        allowCallbacks?: string,
        allowConditionalTypes?: string,
        allowConstructors?: string,
        allowLiterals?: string,
        allowMappedTypes?: string,
        allowTupleTypes?: string,
        allowGenerics?: string
    },
];

const defaultOptions: NoTypeAliasOptions = [
    {
        allowAliases: "never",
        allowCallbacks: "never",
        allowConditionalTypes: "never",
        allowConstructors: "never",
        allowLiterals: "never",
        allowMappedTypes: "never",
        allowTupleTypes: "never",
        allowGenerics: "never"
    },
];

interface MessageInfo {
    noTypeAlias: string,
    noCompositionAlias: string,
}

export class NoTypeAliasCheck implements BaseChecker {
    issues: IssueReport[] = [];
    readonly CONST_STR: string = "const";
    readonly CONST_LET: string = "let";
    readonly CONST_CONSTRUCTOR: string = "constructor";
    readonly CONST_EQUAL: string = "=";
    readonly CONST_ARROW: string = "=>";

    private options: NoTypeAliasOptions;
    private messages: MessageInfo = {
        noTypeAlias: 'Type & are not allowed.',
        noCompositionAlias: '& in * types are not allowed.',
    };
    public rule: Rule;
    public defects: Defects[] = [];

    public metaData: BaseMetaData = {
        severity: 2,
        ruleDocPath: 'docs/no-type-alias-check.md',
        description: '',
    };

    private fieldMatcher: FieldMatcher = {
        matcherType: MatcherTypes.FIELD,
    };

    private fileMatcher: FileMatcher = {
        matcherType: MatcherTypes.FILE,
    };

    private clsMatcher: ClassMatcher = {
        matcherType: MatcherTypes.CLASS,
    };

    private methodMatcher: MethodMatcher = {
        matcherType: MatcherTypes.METHOD,
        class: [this.clsMatcher],
        file: [this.fileMatcher],
    };

    public registerMatchers(): MatcherCallback[] {
        const classMatcherCb: MatcherCallback = {
            matcher: this.clsMatcher,
            callback: this.check,
        };
        return [classMatcherCb];
    }

    private getMessage(templateText: string, replaceText1: string, replaceText2?: string,): string {
        if (replaceText2) {
            return templateText.replace("&", replaceText1).replace("*", replaceText2);
        }
        return templateText.replace("&", replaceText1);
    }

    public check = (target: ArkClass) => {
        this.options = this.getDefaultOption();
        if (target instanceof ArkClass) {
            const filePath = target.getDeclaringArkFile().getFilePath();
            if(filePath.endsWith(".ts")) {
                const map = target.getDefaultArkMethod()?.getBody()?.getAliasTypeMap();
                map?.forEach((value: [AliasType, ArkAliasTypeDefineStmt]) => {
                    this.checkAliases(value[0], value[1], target);
                    this.checkCallbacks(value[0], value[1], target);
                    this.checkConditionalTypes(value[0], value[1], target);
                    this.checkConstructors(value[0], value[1], target);
                    this.checkLiterals(value[0], value[1], target);
                    this.checkMappedTypes(value[0], value[1], target);
                    this.checkTupleTypes(value[0], value[1], target);
                    this.checkGenerics(value[0], value[1], target);
                })
            }
        }
    };

    private checkGenerics(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        if (this.options[0].allowGenerics === "never") {
            if (originalType instanceof ClassType) {
                const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<");
                if (hasGenerics) {
                    const message = this.getMessage(this.messages.noTypeAlias, "generics");
                    this.addIssueReport(declaration, clazz, message, originalType.getClassSignature().getClassName());
                }
            } else if(originalType instanceof UnclearReferenceType) {
                const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<");
                if (hasGenerics) {
                    const message = this.getMessage(this.messages.noTypeAlias, "generics");
                    this.addIssueReport(declaration, clazz, message, originalType.getName());
                }
            }
        }
    }

    private checkTupleTypes(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        if (this.options[0].allowTupleTypes === "never") {
            if (originalType instanceof TupleType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                const message = this.getMessage(this.messages.noTypeAlias, "tuple");
                this.addIssueReport(declaration, clazz, message, rightText);
            } else if (originalType instanceof UnionType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                const split = rightText.split("|");
                const message = this.getMessage(this.messages.noCompositionAlias, "Tuple", "union");
                for (var i = 0; i < split.length; i++) {
                    if (split[i].trim().startsWith("[")) {
                        this.addIssueReport(declaration, clazz, message, split[i].trim());
                    } else {
                        if (split[i].trim().includes("&")) {
                            const s = split[i].trim().split("&");
                            const message = this.getMessage(this.messages.noCompositionAlias, "Tuple", "intersection");
                            for (var i = 0; i < s.length; i++) {
                                if (s[i].trim().startsWith("[")) {
                                    this.addIssueReport(declaration, clazz, message, s[i].trim());
                                } else if (s[i].trim().includes("[")) {
                                    const t = s[i].trim().substring(s[i].trim().indexOf("["));
                                    this.addIssueReport(declaration, clazz, message, t);
                                }
                            }
                        }
                    }
                }
            } else if (originalType instanceof UnknownType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                if (rightText.includes("&")) {
                    const split = rightText.split("&");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Tuple", "intersection");
                    for (var i = 0; i < split.length; i++) {
                        if (split[i].trim().startsWith("[")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                }
            }
        } else if (this.options[0].allowTupleTypes === "in-unions") {
            if (originalType instanceof TupleType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                const message = this.getMessage(this.messages.noTypeAlias, "tuple");
                this.addIssueReport(declaration, clazz, message, rightText);
            } else if (originalType instanceof UnionType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                const split = rightText.split("|");
                // const message = this.getMessage(this.messages.noCompositionAlias, "Tuple", "union");
                for (var i = 0; i < split.length; i++) {
                    if (split[i].trim().startsWith("[")) {
                        // this.addIssueReport(declaration, clazz, message, split[i].trim());
                    } else {
                        if (split[i].trim().includes("&")) {
                            const s = split[i].trim().split("&");
                            const message = this.getMessage(this.messages.noCompositionAlias, "Tuple", "intersection");
                            for (var i = 0; i < s.length; i++) {
                                if (s[i].trim().startsWith("[")) {
                                    this.addIssueReport(declaration, clazz, message, s[i].trim());
                                } else if (s[i].trim().includes("[")) {
                                    const t = s[i].trim().substring(s[i].trim().indexOf("["));
                                    this.addIssueReport(declaration, clazz, message, t);
                                }
                            }
                        }
                    }
                }
            } else if (originalType instanceof UnknownType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                if (rightText.includes("&")) {
                    const split = rightText.split("&");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Tuple", "intersection");
                    for (var i = 0; i < split.length; i++) {
                        if (split[i].trim().startsWith("[")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                }
            }
        } else if (this.options[0].allowTupleTypes === "in-intersections") {
            if (originalType instanceof TupleType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                const message = this.getMessage(this.messages.noTypeAlias, "tuple");
                this.addIssueReport(declaration, clazz, message, rightText);
            } else if (originalType instanceof UnionType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                const split = rightText.split("|");
                const message = this.getMessage(this.messages.noCompositionAlias, "Tuple", "union");
                for (var i = 0; i < split.length; i++) {
                    if (split[i].trim().startsWith("[")) {
                        this.addIssueReport(declaration, clazz, message, split[i].trim());
                    }
                }
            }
        } else if (this.options[0].allowTupleTypes === "in-unions-and-intersections") {
            if (originalType instanceof TupleType) {
                const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                const message = this.getMessage(this.messages.noTypeAlias, "tuple");
                this.addIssueReport(declaration, clazz, message, rightText);
            }
        }
    }

    private checkMappedTypes(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        const name = type.getName();
        const sourceCode = declaration.getOriginalText()!;
        const nameRightText = sourceCode.substring(sourceCode.indexOf(name) + name.length).trim();
        if (nameRightText.startsWith("<")) {
            if (this.options[0].allowMappedTypes === "never") {
                //停用该功能
                if (originalType instanceof UnknownType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    if (rightText.startsWith("{")) {
                        if (rightText.includes("&")) {
                            const message = this.getMessage(this.messages.noCompositionAlias, "Mapped", "intersection");
                            const split = rightText.split("&");
                            for (var i = 0; i < split.length; i++) {
                                if (split[i].trim().startsWith("{")) {
                                    this.addIssueReport(declaration, clazz, message, split[i].trim());
                                }
                            }
                        } else {
                            const message = this.getMessage(this.messages.noTypeAlias, "mapped");
                            this.addIssueReport(declaration, clazz, message, rightText);
                        }
                    }
                } else if (originalType instanceof UnionType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("|");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Mapped", "union");
                    for (var i = 0; i < split.length; i++) {
                        if (split[i].trim().startsWith("{")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                }
            } else if (this.options[0].allowMappedTypes === "in-unions") {
                //允许在 union 语句中使用别名，例如 type Foo = string | string[];
                if (originalType instanceof UnknownType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    if (rightText.startsWith("{")) {
                        if (rightText.includes("&")) {
                            const message = this.getMessage(this.messages.noCompositionAlias, "Mapped", "intersection");
                            const split = rightText.split("&");
                            for (var i = 0; i < split.length; i++) {
                                if (split[i].trim().startsWith("{")) {
                                    this.addIssueReport(declaration, clazz, message, split[i].trim());
                                }
                            }
                        } else {
                            const message = this.getMessage(this.messages.noTypeAlias, "mapped");
                            this.addIssueReport(declaration, clazz, message, rightText);
                        }
                    }
                }
            } else if (this.options[0].allowMappedTypes === "in-intersections") {
                //允许在交集语句中使用别名，例如 type Foo = string & string[];
                if (originalType instanceof UnknownType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    if (rightText.startsWith("{")) {
                        if (!rightText.includes("&")) {
                            const message = this.getMessage(this.messages.noTypeAlias, "mapped");
                            this.addIssueReport(declaration, clazz, message, rightText);
                        }
                    }
                } else if (originalType instanceof UnionType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("|");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Mapped", "union");
                    for (var i = 0; i < split.length; i++) {
                        if (split[i].trim().startsWith("{")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                }
            } else if (this.options[0].allowMappedTypes === "in-unions-and-intersections") {
                //允许在并集和/或交集语句中使用别名。
                if (originalType instanceof UnknownType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    if (rightText.startsWith("{")) {
                        if (!rightText.includes("&")) {
                            const message = this.getMessage(this.messages.noTypeAlias, "mapped");
                            this.addIssueReport(declaration, clazz, message, rightText);
                        }
                    }
                }
            }
        }

    }

    private checkLiterals(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        const name = type.getName();
        const sourceCode = declaration.getOriginalText()!;
        const nameRightText = sourceCode.substring(sourceCode.indexOf(name) + name.length).trim();
        if (!nameRightText.startsWith("<")) {
            if (this.options[0].allowLiterals === "never") {
                //停用该功能
                if (originalType instanceof ClassType) {
                    const split = declaration.getOriginalText()!.split("=");
                    const rightText = split[1].trim();
                    if (rightText.startsWith("{")) {
                        const message = this.getMessage(this.messages.noTypeAlias, "literals");
                        this.addIssueReport(declaration, clazz, message, rightText);
                    }
                } else if (originalType instanceof UnionType) {
                    const types = originalType.getTypes();
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("|");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Literals", "union");
                    for (var i = 0; i < types.length; i++) {
                        if (split[i].trim().startsWith("{")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                } else if (originalType instanceof UnknownType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("&");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Literals", "intersection");
                    for (var i = 0; i < split.length; i++) {
                        if (split[i].trim().startsWith("{")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                }

            } else if (this.options[0].allowLiterals === "in-unions") {
                //允许在 union 语句中使用字面量，例如 type Foo = string | string[];
                if (originalType instanceof ClassType) {
                    const split = declaration.getOriginalText()!.split("=");
                    const rightText = split[1].trim();
                    if (rightText.startsWith("{")) {
                        const message = this.getMessage(this.messages.noTypeAlias, "literals");
                        this.addIssueReport(declaration, clazz, message, rightText);
                    }
                } else if (originalType instanceof UnknownType) {
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("&");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Literals", "intersection");
                    for (var i = 0; i < split.length; i++) {
                        if (split[i].trim().startsWith("{")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                }

            } else if (this.options[0].allowLiterals === "in-intersections") {
                //允许在交集语句中使用字面量，例如 type Foo = string & string[];
                if (originalType instanceof ClassType) {
                    const split = declaration.getOriginalText()!.split("=");
                    const rightText = split[1].trim();
                    if (rightText.startsWith("{")) {
                        const message = this.getMessage(this.messages.noTypeAlias, "literals");
                        this.addIssueReport(declaration, clazz, message, rightText);
                    }
                } else if (originalType instanceof UnionType) {
                    const types = originalType.getTypes();
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("|");
                    const message = this.getMessage(this.messages.noCompositionAlias, "Literals", "union");
                    for (var i = 0; i < types.length; i++) {
                        if (split[i].trim().startsWith("{")) {
                            this.addIssueReport(declaration, clazz, message, split[i].trim());
                        }
                    }
                }

            } else if (this.options[0].allowLiterals === "in-unions-and-intersections") {
                //允许并集和/或交集语句中的字面量
                if (originalType instanceof ClassType) {
                    const split = declaration.getOriginalText()!.split("=");
                    const rightText = split[1].trim();
                    if (rightText.startsWith("{")) {
                        const message = this.getMessage(this.messages.noTypeAlias, "literals");
                        this.addIssueReport(declaration, clazz, message, rightText);
                    }
                }
            }
        }

    }

    private checkConstructors(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        if (this.options[0].allowConstructors === "never") {
            if (originalType instanceof UnknownType) {
                const message = this.getMessage(this.messages.noTypeAlias, "constructors");
                const split = declaration.getOriginalText()!.split("=");
                const rightText = split[1].trim();
                if (rightText.startsWith("new")) {
                    this.addIssueReport(declaration, clazz, message, rightText);
                }
            }
        }
    }

    private checkConditionalTypes(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        if (this.options[0].allowConditionalTypes === "never") {
            const name = type.getName();
            const sourceCode = declaration.getOriginalText()!;
            const rightText = sourceCode.substring(sourceCode.indexOf(name) + name.length).trim();
            const equalRightText = sourceCode.substring(sourceCode.indexOf("=") + 1).trim();
            if (rightText.startsWith("<") && !(equalRightText.startsWith("{") || equalRightText.startsWith("|"))) {
                const message = this.getMessage(this.messages.noTypeAlias, "conditional");
                const split = declaration.getOriginalText()!.split("=");
                this.addIssueReport(declaration, clazz, message, split[1].trim());
            }
        }
    }

    private checkCallbacks(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        if (this.options[0].allowCallbacks === "never") {
            if (originalType instanceof FunctionType) {
                const message = this.getMessage(this.messages.noTypeAlias, "callbacks");
                const split = declaration.getOriginalText()!.split("=");
                this.addIssueReport(declaration, clazz, message, split[1].trim());
            }
        }
    }

    private checkAliases(type: AliasType, declaration: ArkAliasTypeDefineStmt, clazz: ArkClass) {
        const originalType = type.getOriginalType();
        if (this.options[0].allowAliases === "never") {
            //停用该功能
            if (originalType instanceof LiteralType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getLiteralName().toString());
            } else if (originalType instanceof UnionType) {
                const types = originalType.getTypes();
                if (types.length === 1) {
                    const t = types[0];
                    if (t instanceof LiteralType) {
                        const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                        if (declaration.getOriginalText()!.includes("`")) {
                            this.addIssueReport(declaration, clazz, message, "`");
                        } else {
                            this.addIssueReport(declaration, clazz, message, t.getLiteralName().toString());
                        }
                    }
                } else {
                    types.forEach((t) => {
                        let message = this.getMessage(this.messages.noCompositionAlias, "Aliases", "union");
                        if (t instanceof LiteralType) {
                            this.addIssueReport(declaration, clazz, message, t.getLiteralName().toString());
                        } else if (t instanceof StringType) {
                            this.addIssueReport(declaration, clazz, message, t.getTypeString());
                        } else if (t instanceof ArrayType) {
                            this.addIssueReport(declaration, clazz, message, t.getTypeString());
                        } else if (t instanceof ClassType) {
                            const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<")
                            if (!t.getClassSignature().getClassName().startsWith("%") && !hasGenerics) {
                                this.addIssueReport(declaration, clazz, message, t.getClassSignature().getClassName());
                            }
                        }
                    })
                }

            } else if (originalType instanceof StringType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getName().toString());
            } else if (originalType instanceof UnknownType) {
                if (declaration.getOriginalText()!.includes("&")) {
                    const message = this.getMessage(this.messages.noCompositionAlias, "Aliases", "intersection");
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("&");
                    split.forEach((s) => {
                        if (!s.trim().startsWith("{") && !s.trim().startsWith("[")) {
                            this.addIssueReport(declaration, clazz, message, s.trim());
                        }
                    })
                }
            } else if (originalType instanceof ClassType) {
                const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<")
                if (!originalType.getClassSignature().getClassName().startsWith("%") && !hasGenerics) {
                    const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                    this.addIssueReport(declaration, clazz, message, originalType.getClassSignature().getClassName());
                }
            }

        } else if (this.options[0].allowAliases === "in-unions") {
            //允许在 union 语句中使用别名，例如 type Foo = string | string[];

            if (originalType instanceof LiteralType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getLiteralName().toString());
            } else if (originalType instanceof UnionType) {
                const types = originalType.getTypes();
                if (types.length === 1) {
                    const t = types[0];
                    if (t instanceof LiteralType) {
                        const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                        if (declaration.getOriginalText()!.includes("`")) {
                            this.addIssueReport(declaration, clazz, message, "`");
                        } else {
                            this.addIssueReport(declaration, clazz, message, t.getLiteralName().toString());
                        }
                    }
                }

            } else if (originalType instanceof StringType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getName().toString());
            } else if (originalType instanceof UnknownType) {
                if (declaration.getOriginalText()!.includes("&")) {
                    const message = this.getMessage(this.messages.noCompositionAlias, "Aliases", "intersection");
                    const rightText = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim();
                    const split = rightText.split("&");
                    split.forEach((s) => {
                        if (!s.trim().startsWith("{") && !s.trim().startsWith("[")) {
                            this.addIssueReport(declaration, clazz, message, s.trim());
                        }
                    })
                }
            } else if (originalType instanceof ClassType) {
                const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<")
                if (!originalType.getClassSignature().getClassName().startsWith("%") && !hasGenerics) {
                    const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                    this.addIssueReport(declaration, clazz, message, originalType.getClassSignature().getClassName());
                }
            }

        } else if (this.options[0].allowAliases === "in-intersections") {
            //允许在交集语句中使用别名，例如 type Foo = string & string[];
            if (originalType instanceof LiteralType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getLiteralName().toString());
            } else if (originalType instanceof UnionType) {
                const types = originalType.getTypes();
                if (types.length === 1) {
                    const t = types[0];
                    if (t instanceof LiteralType) {
                        const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                        if (declaration.getOriginalText()!.includes("`")) {
                            this.addIssueReport(declaration, clazz, message, "`");
                        } else {
                            this.addIssueReport(declaration, clazz, message, t.getLiteralName().toString());
                        }
                    }
                } else {
                    types.forEach((t) => {
                        let message = this.getMessage(this.messages.noCompositionAlias, "Aliases", "union");
                        if (t instanceof LiteralType) {
                            this.addIssueReport(declaration, clazz, message, t.getLiteralName().toString());
                        } else if (t instanceof StringType) {
                            this.addIssueReport(declaration, clazz, message, t.getTypeString());
                        } else if (t instanceof ArrayType) {
                            this.addIssueReport(declaration, clazz, message, t.getTypeString());
                        } else if (t instanceof ClassType) {
                            const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<")
                            if (!t.getClassSignature().getClassName().startsWith("%") && !hasGenerics) {
                                this.addIssueReport(declaration, clazz, message, t.getClassSignature().getClassName());
                            }
                        }
                    })
                }

            } else if (originalType instanceof StringType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getName().toString());
            } else if (originalType instanceof ClassType) {
                const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<")
                if (!originalType.getClassSignature().getClassName().startsWith("%") && !hasGenerics) {
                    const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                    this.addIssueReport(declaration, clazz, message, originalType.getClassSignature().getClassName());
                }
            }

        } else if (this.options[0].allowAliases === "in-unions-and-intersections") {
            //允许在并集和/或交集语句中使用别名。
            if (originalType instanceof LiteralType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getLiteralName().toString());
            } else if (originalType instanceof UnionType) {
                const types = originalType.getTypes();
                if (types.length === 1) {
                    const t = types[0];
                    if (t instanceof LiteralType) {
                        const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                        if (declaration.getOriginalText()!.includes("`")) {
                            this.addIssueReport(declaration, clazz, message, "`");
                        } else {
                            this.addIssueReport(declaration, clazz, message, t.getLiteralName().toString());
                        }
                    }
                }

            } else if (originalType instanceof StringType) {
                const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                this.addIssueReport(declaration, clazz, message, originalType.getName().toString());
            } else if (originalType instanceof ClassType) {
                const hasGenerics = declaration.getOriginalText()!.substring(declaration.getOriginalText()!.indexOf("=") + 1).trim().includes("<")
                if (!originalType.getClassSignature().getClassName().startsWith("%") && !hasGenerics) {
                    const message = this.getMessage(this.messages.noTypeAlias, "aliases");
                    this.addIssueReport(declaration, clazz, message, originalType.getClassSignature().getClassName());
                }
            }

        }
    }

    public getDefaultOption(): NoTypeAliasOptions {
        let option: NoTypeAliasOptions;
        if (this.rule && this.rule.option) {
            option = this.rule.option as NoTypeAliasOptions;
            if (option[0]) {
                if (!option[0].allowAliases) {
                    option[0].allowAliases = "never";
                }
                if (!option[0].allowCallbacks) {
                    option[0].allowCallbacks = "never";
                }
                if (!option[0].allowConditionalTypes) {
                    option[0].allowConditionalTypes = "never";
                }
                if (!option[0].allowConstructors) {
                    option[0].allowConstructors = "never";
                }
                if (!option[0].allowLiterals) {
                    option[0].allowLiterals = "never";
                }
                if (!option[0].allowMappedTypes) {
                    option[0].allowMappedTypes = "never";
                }
                if (!option[0].allowTupleTypes) {
                    option[0].allowTupleTypes = "never";
                }
                if (!option[0].allowGenerics) {
                    option[0].allowGenerics = "never";
                }
                return option;
            }

        }
        return defaultOptions;
    }

    private addIssueReport(declaration: ArkAliasTypeDefineStmt, clazz: ArkClass, description: string, text: string) {
        let currDescription = description ? description : this.metaData.description;
        const severity = this.rule.alert ?? this.metaData.severity;
        const warnInfo = this.getLineAndColumn(declaration, clazz, text);
        const fixKey = warnInfo.line + '%' + warnInfo.startCol + '%' + this.rule.ruleId;
        const mergeKey = warnInfo.filePath + '%' + fixKey + '%' + currDescription;
        const defect = new Defects(warnInfo.line!, warnInfo.startCol, currDescription, severity, this.rule.ruleId,
            mergeKey, this.metaData.ruleDocPath, true, false, false, fixKey);
        this.issues.push(new IssueReport(defect, undefined));
        RuleListUtil.push(defect);
    }

    private getLineAndColumn(declaration: ArkAliasTypeDefineStmt, clazz: ArkClass, text: string) {
        const originPosition = declaration.getOriginPositionInfo();
        let line = originPosition.getLineNo();
        const arkFile = clazz.getDeclaringArkFile();
        if (arkFile) {
            let originText = declaration.getOriginalText()! ?? '';
            let startCol = originPosition.getColNo();
            const count = this.countOccurrences(originText.substring(0, originText.indexOf(text)), "\n");
            line += count;
            let pos = originText.indexOf(text);
            if (count > 0) {
                const split = originText.substring(0, originText.indexOf(text)).split("\n");
                const last = split.pop();
                pos = last?.length ?? 0 + 1;
            }
            if (pos !== -1) {
                startCol += pos;
                const endCol = startCol + text.length;
                const originPath = arkFile.getFilePath();
                return { line, startCol, endCol, filePath: originPath }
            }
        } else {
            logger.debug('arkFile is null');
        }
        return { line: -1, startCol: -1, endCol: -1, filePath: '' };
    }

    /**
     * 计算一个字符串包含另一个字符串的次数
     * @param haystack  要搜索的字符串
     * @param needle 要查找的子字符串
     * @returns 子字符串出现的次数
     */
    private countOccurrences(haystack: string, needle: string): number {
        if (!needle) {
            return 0; // 如果要查找的字符串为空，返回0次
        }

        const regex = new RegExp(needle, 'g');
        const matches = [...haystack.matchAll(regex)];

        return matches.length;
    }
}
